// Rust有几个保留的生命周期，其中static就是一个
// 可以在两种情况下用到

// A reference with 'static lifetime: 
// 一个引用变量具有static生命周期
// let s: &'static str = "hello world";

// 'static as part of a trait bound: 
// 作为trait bound 有静态生命周期
// fn generic<T>(x: T) where T: 'static {}

// 上面的两种情况有细微的差别，容易迷惑
// 1:引用变量的生命周期

// Make a constant with `'static` lifetime.
static NUM: i32 = 18;

// Returns a reference to `NUM` where its `'static`
// lifetime is coerced to that of the input argument.
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
    &NUM
}

use rand::Rng;
use rand::Fill;

fn random_vec() -> &'static [usize; 100] {
    let mut rng = rand::thread_rng();
    let mut boxed = Box::new([0; 100]);
    // boxed.try_fill(&mut rng).unwrap();
    // 返回静态生命周期，动态创建静态生命周期
    Box::leak(boxed)
}

// -------------- Trait bound ------------------------------------------
use std::fmt::Debug;

fn print_it(input : impl Debug +'static ){
    println!("'static value passed in is: {:?}", input);
}
fn main() {
    {
        // Make a `string` literal and print it:
        let static_string = "I'm in read-only memory";
        println!("static_string: {}", static_string);

        // When `static_string` goes out of scope, the reference
        // can no longer be used, but the data remains in the binary.
    }

    {
        // Make an integer to use for `coerce_static`:
        let lifetime_num = 9;

        // Coerce `NUM` to lifetime of `lifetime_num`:
        let coerced_static = coerce_static(&lifetime_num);

        println!("coerced_static: {}", coerced_static);
    }

    println!("NUM: {} stays accessible!", NUM);

    //------- Box::leak(boxed) 会创建一个 'static 引用 
    let first: &'static [usize; 100] = random_vec();
    let second: &'static [usize; 100] = random_vec();
    println!("first :{:#?}", first);
    println!("secodn:{:#?}", second);
    assert_ne!(first, second);

    //------- Trait bound ------------------------
    // i is owned and contains no references, thus it's 'static:
    let i = 5;
    print_it(i);

    // oops, &i only has the lifetime defined by the scope of
    // main(), so it's not 'static:
    // print_it(&i);

}